/*
 * functions (possibly) linked in, complete, from libc.
 */
#define nelem(x)        (sizeof(x)/sizeof((x)[0]))
#define offsetof(s, m)  (ulong)(&(((s*)0)->m))
//#define assert(x)       if(x){}else _assert("x")

/*
 * mem routines

extern  void*   memccpy(void*, void*, int, ulong);
extern  void*   memset(void*, int, ulong);
extern  int     memcmp(void*, void*, ulong);
extern  void*   memmove(void*, void*, ulong);
extern  void*   memchr(void*, int, ulong);
 */

/*
 * string routines
extern  char*   strcat(char*, char*);
extern  char*   strchr(char*, int);
extern  char*   strrchr(char*, int);
extern  int     strcmp(char*, char*);
extern  char*   strcpy(char*, char*);
extern  char*   strecpy(char*, char*, char*);
extern  char*   strncat(char*, char*, long);
extern  char*   strncpy(char*, char*, long);
extern  int     strncmp(char*, char*, long);
extern  long    strlen(char*);
extern  char*   strstr(char*, char*);
extern  int     atoi(char*);
extern  int     fullrune(char*, int);
extern  int     cistrcmp(char*, char*);
extern  int     cistrncmp(char*, char*, int);
 */

enum
{
        UTFmax          = 3,    /* maximum bytes per rune */
        Runesync        = 0x80, /* cannot represent part of a UTF sequence */
        Runeself        = 0x80, /* rune and UTF sequences are the same (<) */
        Runeerror       = 0x80, /* decoding error in UTF */
};

/*
 * rune routines
 */
extern  int     runetochar(char*, Rune*);
extern  int     chartorune(Rune*, char*);
extern  char*   utfrune(char*, long);
extern  int     utflen(char*);
extern  int     utfnlen(char*, long);
extern  int     runelen(long);

extern  int     abs(int);

#if 0
/*
 * print routines
 */
typedef struct Fmt      Fmt;
typedef int (*Fmts)(Fmt*);
struct Fmt{
        uchar   runes;                  /* output buffer is runes or chars? */
        void    *start;                 /* of buffer */
        void    *to;                    /* current place in the buffer */
        void    *stop;                  /* end of the buffer; overwritten if flush fails */
        int     (*flush)(Fmt *);        /* called when to == stop */
        void    *farg;                  /* to make flush a closure */
        int     nfmt;                   /* num chars formatted so far */
        va_list args;                   /* args passed to dofmt */
        int     r;                      /* % format Rune */
        int     width;
        int     prec;
        ulong   flags;
};
extern  int     print(char*, ...);
extern  char*   seprint(char*, char*, char*, ...);
//extern  char*   vseprint(char*, char*, char*, va_list);
extern  int     snprint(char*, int, char*, ...);
//extern  int     vsnprint(char*, int, char*, va_list);
extern  int     sprint(char*, char*, ...);


//#if 0
#pragma varargck        argpos  fmtprint        2
#pragma varargck        argpos  print           1
#pragma varargck        argpos  seprint         3
#pragma varargck        argpos  snprint         3
#pragma varargck        argpos  sprint          2

#pragma varargck        type    "llb"   vlong
#pragma varargck        type    "lld"   vlong
#pragma varargck        type    "llx"   vlong
#pragma varargck        type    "llb"   uvlong
#pragma varargck        type    "lld"   uvlong
#pragma varargck        type    "llx"   uvlong
#pragma varargck        type    "lb"    long
#pragma varargck        type    "ld"    long
#pragma varargck        type    "lx"    long
#pragma varargck        type    "lb"    ulong
#pragma varargck        type    "ld"    ulong
#pragma varargck        type    "lx"    ulong
#pragma varargck        type    "b"     int
#pragma varargck        type    "d"     int
#pragma varargck        type    "x"     int
#pragma varargck        type    "c"     int
#pragma varargck        type    "C"     int
#pragma varargck        type    "b"     uint
#pragma varargck        type    "d"     uint
#pragma varargck        type    "x"     uint
#pragma varargck        type    "c"     uint
#pragma varargck        type    "C"     uint
#pragma varargck        type    "s"     char*
#pragma varargck        type    "q"     char*
#pragma varargck        type    "S"     Rune*
#pragma varargck        type    "%"     void
#pragma varargck        type    "p"     uintptr
#pragma varargck        type    "p"     void*
#pragma varargck        flag    ','

extern  int     fmtstrinit(Fmt*);
extern  int     fmtinstall(int, int (*)(Fmt*));
extern  void    quotefmtinstall(void);
extern  int     fmtprint(Fmt*, char*, ...);
extern  int     fmtstrcpy(Fmt*, char*);
extern  char*   fmtstrflush(Fmt*);
#endif

/*
 * one-of-a-kind
 * /
extern  char*   cleanname(char*);
extern  ulong   getcallerpc(void*);

extern  long    strtol(char*, char**, int);
extern  ulong   strtoul(char*, char**, int);
extern  vlong   strtoll(char*, char**, int);
extern  uvlong  strtoull(char*, char**, int);
extern  char    etext[];
extern  char    edata[];
extern  char    end[];
extern  int     getfields(char*, char**, int, int, char*);
extern  int     tokenize(char*, char**, int);
extern  int     dec64(uchar*, int, char*, int);
//extern  int     encodefmt(Fmt*);
extern  void    qsort(void*, long, long, int (*)(void*, void*));
*/

/*
 * Syscall data structures
 */
#define MORDER  0x0003  /* mask for bits defining order of mounting */
#define MREPL   0x0000  /* mount replaces object */
#define MBEFORE 0x0001  /* mount goes before others in union directory */
#define MAFTER  0x0002  /* mount goes after others in union directory */
#define MCREATE 0x0004  /* permit creation in mounted directory */
#define MCACHE  0x0010  /* cache some data */
#define MMASK   0x0017  /* all bits on */

#define OREAD   0       /* open for read */
#define OWRITE  1       /* write */
#define ORDWR   2       /* read and write */
#define OEXEC   3       /* execute, == read but check execute permission */
#define OTRUNC  16      /* or'ed in (except for exec), truncate file first */
#define OCEXEC  32      /* or'ed in, close on exec */
#define ORCLOSE 64      /* or'ed in, remove on close */
#define OEXCL   0x1000  /* or'ed in, exclusive create */

#define NCONT   0       /* continue after note */
#define NDFLT   1       /* terminate after note */
#define NSAVE   2       /* clear note but hold state */
#define NRSTR   3       /* restore saved state */

typedef struct Qid      Qid;
typedef struct Dir      Dir;
typedef struct OWaitmsg OWaitmsg;
typedef struct Waitmsg  Waitmsg;

#define ERRMAX                  128     /* max length of error string */
#define KNAMELEN                28      /* max length of name held in kernel */

/* bits in Qid.type */
#define QTDIR           0x80            /* type bit for directories */
#define QTAPPEND        0x40            /* type bit for append only files */
#define QTEXCL          0x20            /* type bit for exclusive use files */
#define QTMOUNT         0x10            /* type bit for mounted channel */
#define QTAUTH          0x08            /* type bit for authentication file */
#define QTFILE          0x00            /* plain file */

/* bits in Dir.mode */
#define DMDIR           0x80000000      /* mode bit for directories */
#define DMAPPEND        0x40000000      /* mode bit for append only files */
#define DMEXCL          0x20000000      /* mode bit for exclusive use files */
#define DMMOUNT         0x10000000      /* mode bit for mounted channel */
#define DMREAD          0x4             /* mode bit for read permission */
#define DMWRITE         0x2             /* mode bit for write permission */
#define DMEXEC          0x1             /* mode bit for execute permission */

struct Qid
{
        uvlong  path;
        ulong   vers;
        uchar   type;
};

struct Dir {
        /* system-modified data */
        ushort  type;   /* server type */
        uint    dev;    /* server subtype */
        /* file data */
        Qid     qid;    /* unique id from server */
        ulong   mode;   /* permissions */
        ulong   atime;  /* last read time */
        ulong   mtime;  /* last write time */
        vlong   length; /* file length: see <u.h> */
        char    *name;  /* last element of path */
        char    *uid;   /* owner name */
        char    *gid;   /* group name */
        char    *muid;  /* last modifier name */
};

struct OWaitmsg
{
        char    pid[12];        /* of loved one */
        char    time[3*12];     /* of loved one and descendants */
        char    msg[64];        /* compatibility BUG */
};

struct Waitmsg
{
        int     pid;            /* of loved one */
        ulong   time[3];        /* of loved one and descendants */
        char    msg[ERRMAX];    /* actually variable-size in user mode */
};

